#include <TFT_eSPI.h>
TFT_eSPI tft = TFT_eSPI();

#define BLINKER_WIFI
#include <WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include <DHT.h>
#include <Wire.h>
#include <BH1750.h>
#include <Blinker.h>
#include <ESP32Servo.h>

// Sensor definitions
#define DHTPIN 15
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
float temperature;
float humidity;

// Light sensor
BH1750 lightMeter;
const uint16_t MAX_LUX = 1000;

// Soil moisture sensor
const int soilMoisturePin = 34;
float soilMoisturePercentage;

// Physical buttons
#define K1_PIN 27  // Servo control
#define K2_PIN 25  // Fan control
#define K3_PIN 19  // Heating control
#define K4_PIN 18  // Pump control

// Button states
int servoButtonState = HIGH;
int fanButtonState = HIGH;
int heaterButtonState = HIGH;
int pumpButtonState = HIGH;

// Last button states
int lastServoButtonState = HIGH;
int lastFanButtonState = HIGH;
int lastHeaterButtonState = HIGH;
int lastPumpButtonState = HIGH;

// Device states
String servoState = "115°";
String fanState = "OFF";
String heaterState = "OFF";
String pumpState = "OFF";

// Button debouncing
unsigned long lastDebounceTime = 0;
const unsigned long debounceDelay = 50;

// MQTT configuration
//连接参数
const char* ssid = "y";//wif名称
const char* password = "0987654321";//wifi密码
//华为云MQTT连接参数
const char* Iot_link_MQTT_Topic_Report = "修改";
const char* commandTopic = "修改";
const char* mqttServer = "修改";
const int mqttPort = 1883;
const char* clientId = "修改";
const char* mqttUser = "修改";
const char* mqttPassword = "修改";

WiFiClient espClient;
PubSubClient mqttClient(espClient);
unsigned long lastReconnectAttempt = 0;
const unsigned long reconnectInterval = 5000; // 5秒重连间隔

// Servo
Servo myservo;
int servoPin = 16;
const int SERVO_MIN_ANGLE = 10;
const int SERVO_MAX_ANGLE = 115;
int servoAngle = SERVO_MAX_ANGLE;

// Heating module
const int heatingModulePin = 17;

// Fan module
const int inAPin = 32;
const int inBPin = 33;

// Water pump
const int relayPin = 26;

// Blinker configuration
char auth[] = "22b87bf81b46";

// Blinker components
//blinker按键定义
BlinkerButton Button_fszz("fszz");
BlinkerButton Button_fsg("fsg");
BlinkerButton Button_fsfz("fsfz");
BlinkerButton Button_jrk("jrk");
BlinkerButton Button_jrg("jrg");
BlinkerButton Button_sbk("sbk");
BlinkerButton Button_sbg("sbg");
BlinkerSlider Slider_servo("djjd");
BlinkerText fszt("fszt");
BlinkerText sbzt("sbzt");
BlinkerText jrzt("jrzt");
BlinkerNumber kqwd("kqwd");
BlinkerNumber kqsd("kqsd");
BlinkerNumber trsd("trsd");
BlinkerNumber gz("gz");

// Timing variables
unsigned long lastMQTTPostTime = 0;
const unsigned long MQTT_POST_INTERVAL = 10000;
unsigned long lastBlinkerCheckTime = 0;
const unsigned long BLINKER_CHECK_INTERVAL = 100;
unsigned long lastDisplayUpdateTime = 0;
const unsigned long DISPLAY_UPDATE_INTERVAL = 1000;
unsigned long lastButtonCheckTime = 0;
const unsigned long BUTTON_CHECK_INTERVAL = 20;

// Fan control callbacks
void button_fszz_callback(const String & state) {
    if (state == "on") {
        digitalWrite(inAPin, HIGH);
        digitalWrite(inBPin, LOW);
        fanState = "Forward";
        fszt.print(fanState);
    }
}

void button_fsg_callback(const String & state) {
    if (state == "on") {
        digitalWrite(inAPin, LOW);
        digitalWrite(inBPin, LOW);
        fanState = "OFF";
        fszt.print(fanState);
    }
}

void button_fsfz_callback(const String & state) {
    if (state == "on") {
        digitalWrite(inAPin, LOW);
        digitalWrite(inBPin, HIGH);
        fanState = "Reverse";
        fszt.print(fanState);
    }
}

// Heater control callbacks
void button_jrk_callback(const String & state) {
    if (state == "on") {
        digitalWrite(heatingModulePin, HIGH);
        heaterState = "ON";
        jrzt.print(heaterState);
    }
}

void button_jrg_callback(const String & state) {
    if (state == "on") {
        digitalWrite(heatingModulePin, LOW);
        heaterState = "OFF";
        jrzt.print(heaterState);
    }
}

// Pump control callbacks
void button_sbk_callback(const String & state) {
    if (state == "on") {
        digitalWrite(relayPin, LOW);
        pumpState = "ON";
        sbzt.print(pumpState);
    }
}

void button_sbg_callback(const String & state) {
    if (state == "on") {
        digitalWrite(relayPin, HIGH);
        pumpState = "OFF";
        sbzt.print(pumpState);
    }
}

// Servo control callback (限制在10-115度)
void slider_servo_callback(int32_t value) {
    value = constrain(value, SERVO_MIN_ANGLE, SERVO_MAX_ANGLE);
    myservo.write(value);
    servoAngle = value;
    servoState = String(value) + "°";
    Serial.print("Servo set to: ");
    Serial.print(value);
    Serial.println("°");
}

// MQTT callback function
void mqttCallback(char* topic, byte* payload, unsigned int length) {
    if (!mqttClient.connected()) return; // 防止断开时处理消息
    
    Serial.print("Message arrived [");
    Serial.print(topic);
    Serial.print("] ");
    
    // 将payload转换为字符串
    char message[length + 1];
    memcpy(message, payload, length);
    message[length] = '\0';
    Serial.println(message);

    // 解析JSON消息
    DynamicJsonDocument doc(1024);
    DeserializationError error = deserializeJson(doc, message);
    
    if (error) {
        Serial.print("JSON parsing failed: ");
        Serial.println(error.c_str());
        return;
    }

    // 提取命令信息
    const char* commandName = doc["command_name"];
    JsonObject paras = doc["paras"];
    
    Serial.print("Command received: ");
    Serial.println(commandName);

    // 处理不同命令（中文命令名称匹配）
    if (strcmp(commandName, "风扇开关") == 0) {
        const char* fanStateCmd = paras["fan"];
        String stateStr = fanStateCmd;
        stateStr.trim(); // 去除前后空格
        
        Serial.print("Fan command: ");
        if (stateStr == "Forward") {
            Serial.println("正转");
            digitalWrite(inAPin, HIGH);
            digitalWrite(inBPin, LOW);
            fanState = "Forward";
            fszt.print(fanState);
        } else if (stateStr == "Reverse") {
            Serial.println("反转");
            digitalWrite(inAPin, LOW);
            digitalWrite(inBPin, HIGH);
            fanState = "Reverse";
            fszt.print(fanState);
        } else if (stateStr == "OFF") {
            Serial.println("关闭");
            digitalWrite(inAPin, LOW);
            digitalWrite(inBPin, LOW);
            fanState = "OFF";
            fszt.print(fanState);
        } else {
            Serial.println("未知状态");
        }
    } 
    else if (strcmp(commandName, "水泵开关") == 0) {
        const char* pumpStateCmd = paras["SquirtWater"];
        Serial.print("Pump command: ");
        if (strcmp(pumpStateCmd, "ON") == 0) {
            Serial.println("开启");
            digitalWrite(relayPin, LOW);
            pumpState = "ON";
            sbzt.print(pumpState);
        } else if (strcmp(pumpStateCmd, "OFF") == 0) {
            Serial.println("关闭");
            digitalWrite(relayPin, HIGH);
            pumpState = "OFF";
            sbzt.print(pumpState);
        } else {
            Serial.println("未知状态");
        }
    }
    else if (strcmp(commandName, "加热开关") == 0) {
        const char* heaterStateCmd = paras["heating"];
        Serial.print("Heater command: ");
        if (strcmp(heaterStateCmd, "ON") == 0) {
            Serial.println("开启");
            digitalWrite(heatingModulePin, HIGH);
            heaterState = "ON";
            jrzt.print(heaterState);
        } else if (strcmp(heaterStateCmd, "OFF") == 0) {
            Serial.println("关闭");
            digitalWrite(heatingModulePin, LOW);
            heaterState = "OFF";
            jrzt.print(heaterState);
        } else {
            Serial.println("未知状态");
        }
    }
    else {
        Serial.println("Unknown command");
    }

    // 构造响应消息
    String responseTopic = String(topic);
    responseTopic.replace("request", "response");
    String response = "{\"result_code\":0,\"response_name\":\"COMMAND_RESPONSE\",\"paras\":{\"result\":\"success\"}}";
    
    mqttClient.publish(responseTopic.c_str(), response.c_str());
}

bool MQTT_Init() {
    mqttClient.setServer(mqttServer, mqttPort);
    mqttClient.setCallback(mqttCallback);
    mqttClient.setKeepAlive(120);
    
    Serial.println("Attempting MQTT connection...");
    if (mqttClient.connect(clientId, mqttUser, mqttPassword)) {
        Serial.println("Connected to Huawei Cloud IoT Platform");
        
        if (!mqttClient.subscribe(commandTopic)) {
            Serial.println("Subscribe failed, reconnecting...");
            return false;
        }
        Serial.print("Subscribed to topic: ");
        Serial.println(commandTopic);
        return true;
    }
    else {
        Serial.print("failed with state ");
        Serial.print(mqttClient.state());
        return false;
    }
}

void updateDisplay() {
    tft.fillScreen(TFT_BLACK);
    tft.setTextColor(TFT_GREEN, TFT_BLACK);
    tft.setTextSize(1);
    
    tft.setCursor(0, 0);
    tft.print("Temp: ");
    tft.print(temperature);
    tft.println(" C");
    
    tft.setCursor(0, 15);
    tft.print("Humidity: ");
    tft.print(humidity);
    tft.println(" %");
    
    uint16_t lux = lightMeter.readLightLevel();
    uint8_t lightPercentage = (lux * 100 / MAX_LUX > 100)? 100 : lux * 100 / MAX_LUX;
    tft.setCursor(0, 30);
    tft.print("Light: ");
    tft.print(lightPercentage);
    tft.println(" %");
    
    tft.setCursor(0, 45);
    tft.print("SoilMoisture:");
    tft.print(soilMoisturePercentage);
    tft.println(" %");
    
    tft.setCursor(0, 60);
    tft.print("Pump: ");
    tft.println(pumpState);
    
    tft.setCursor(0, 75);
    tft.print("Heater: ");
    tft.println(heaterState);
    
    tft.setCursor(0, 90);
    tft.print("Fan: ");
    tft.println(fanState);
    
    tft.setCursor(0, 105);
    tft.print("Servo: ");
    tft.println(servoState);
}

void MQTT_POST() {
    char jsonBuf[512];

    temperature = dht.readTemperature();
    humidity = dht.readHumidity();

    uint16_t lux = lightMeter.readLightLevel();
    uint8_t lightPercentage = (lux * 100 / MAX_LUX > 100)? 100 : lux * 100 / MAX_LUX;

    // 读取土壤湿度并校准
    int soilMoistureRaw = analogRead(soilMoisturePin);
    soilMoisturePercentage = map(soilMoistureRaw, 0, 4095, 100, 0); // 假设 0 是最湿，4095 是最干
    soilMoisturePercentage = constrain(soilMoisturePercentage, 0, 100);

    snprintf(jsonBuf, sizeof(jsonBuf), "{\"services\":[{\"service_id\":\"Detectiondata\",\"properties\":{\"Airtemperature\":%.2f, \"Airhumidity\":%.2f, \"Soilmoisture\":%.2f, \"Lightintensity\":%u}}]}",
              temperature, humidity, soilMoisturePercentage, lightPercentage);
    mqttClient.publish(Iot_link_MQTT_Topic_Report, jsonBuf);

    Serial.println(Iot_link_MQTT_Topic_Report);
    Serial.println(jsonBuf);
    Serial.println("Publish OK!");
}

void handleButtons() {
    unsigned long currentTime = millis();
    
    // 读取所有按钮状态
    int servoReading = digitalRead(K1_PIN);
    int fanReading = digitalRead(K2_PIN);
    int heaterReading = digitalRead(K3_PIN);
    int pumpReading = digitalRead(K4_PIN);
    
    // 舵机按钮处理
    if (servoReading != lastServoButtonState) {
        lastDebounceTime = currentTime;
    }
    if ((currentTime - lastDebounceTime) > debounceDelay) {
        if (servoReading != servoButtonState) {
            servoButtonState = servoReading;
            if (servoButtonState == LOW) {
                servoAngle = (servoAngle == SERVO_MAX_ANGLE) ? SERVO_MIN_ANGLE : SERVO_MAX_ANGLE;
                myservo.write(servoAngle);
                servoState = String(servoAngle) + "°";
                Serial.print("Servo set to: ");
                Serial.print(servoAngle);
                Serial.println("°");
            }
        }
    }
    lastServoButtonState = servoReading;
    
    // 风扇按钮处理
    if (fanReading != lastFanButtonState) {
        lastDebounceTime = currentTime;
    }
    if ((currentTime - lastDebounceTime) > debounceDelay) {
        if (fanReading != fanButtonState) {
            fanButtonState = fanReading;
            if (fanButtonState == LOW) {
                static int fanMode = 0;
                fanMode = (fanMode + 1) % 3;
                switch(fanMode) {
                    case 0:
                        digitalWrite(inAPin, LOW);
                        digitalWrite(inBPin, LOW);
                        fanState = "OFF";
                        fszt.print(fanState);
                        break;
                    case 1:
                        digitalWrite(inAPin, HIGH);
                        digitalWrite(inBPin, LOW);
                        fanState = "Forward";
                        fszt.print(fanState);
                        break;
                    case 2:
                        digitalWrite(inAPin, LOW);
                        digitalWrite(inBPin, HIGH);
                        fanState = "Reverse";
                        fszt.print(fanState);
                        break;
                }
                Serial.println("Fan: " + fanState);
            }
        }
    }
    lastFanButtonState = fanReading;
    
    // 加热按钮处理
    if (heaterReading != lastHeaterButtonState) {
        lastDebounceTime = currentTime;
    }
    if ((currentTime - lastDebounceTime) > debounceDelay) {
        if (heaterReading != heaterButtonState) {
            heaterButtonState = heaterReading;
            if (heaterButtonState == LOW) {
                heaterState = (heaterState == "OFF") ? "ON" : "OFF";
                digitalWrite(heatingModulePin, (heaterState == "ON") ? HIGH : LOW);
                jrzt.print(heaterState);
                Serial.print("Heater state changed to: ");
                Serial.println(heaterState);
            }
        }
    }
    lastHeaterButtonState = heaterReading;
    
    // 水泵按钮处理
    if (pumpReading != lastPumpButtonState) {
        lastDebounceTime = currentTime;
    }
    if ((currentTime - lastDebounceTime) > debounceDelay) {
        if (pumpReading != pumpButtonState) {
            pumpButtonState = pumpReading;
            if (pumpButtonState == LOW) {
                pumpState = (pumpState == "OFF") ? "ON" : "OFF";
                digitalWrite(relayPin, (pumpState == "ON") ? LOW : HIGH);
                sbzt.print(pumpState);
                Serial.println("Pump: " + pumpState);
            }
        }
    }
    lastPumpButtonState = pumpReading;
}

void setup() {
    Serial.begin(115200);
    
    tft.init();
    tft.setRotation(3);
    tft.fillScreen(TFT_BLACK);
    tft.setTextColor(TFT_GREEN, TFT_BLACK);
    tft.setTextSize(1);
    tft.drawString("Initializing...", 0, 0);
    
    dht.begin();

    pinMode(K1_PIN, INPUT_PULLUP);
    pinMode(K2_PIN, INPUT_PULLUP);
    pinMode(K3_PIN, INPUT_PULLUP);
    pinMode(K4_PIN, INPUT_PULLUP);

    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) {
        delay(1000);
        Serial.print(" ");
    }
    Serial.println("WiFi connected");

    Wire.begin(22, 23);
    lightMeter.begin(BH1750::CONTINUOUS_HIGH_RES_MODE, 0x23);

    analogReadResolution(12);
    pinMode(soilMoisturePin, INPUT);

    MQTT_Init();

    pinMode(inAPin, OUTPUT);
    pinMode(inBPin, OUTPUT);
    digitalWrite(inAPin, LOW);
    digitalWrite(inBPin, LOW);

    myservo.attach(servoPin, 500, 2500);
    myservo.write(SERVO_MAX_ANGLE);
    servoState = String(SERVO_MAX_ANGLE) + "°";

    pinMode(relayPin, OUTPUT);
    digitalWrite(relayPin, HIGH);

    pinMode(heatingModulePin, OUTPUT);
    digitalWrite(heatingModulePin, LOW);
    heaterState = "OFF";

    Blinker.begin(auth, ssid, password);

    Button_fszz.attach(button_fszz_callback);
    Button_fsg.attach(button_fsg_callback);
    Button_fsfz.attach(button_fsfz_callback);
    Button_jrk.attach(button_jrk_callback);
    Button_jrg.attach(button_jrg_callback);
    Button_sbk.attach(button_sbk_callback);
    Button_sbg.attach(button_sbg_callback);
    Slider_servo.attach(slider_servo_callback);
}

void loop() {
    unsigned long currentMillis = millis();

    if (!mqttClient.connected()) {
        if (currentMillis - lastReconnectAttempt > reconnectInterval) {
            lastReconnectAttempt = currentMillis;
            if (MQTT_Init()) {
                Serial.println("Reconnected and resubscribed");
            }
        }
    } else {
        mqttClient.loop();
    }

    if (currentMillis - lastMQTTPostTime >= MQTT_POST_INTERVAL) {
        MQTT_POST();
        lastMQTTPostTime = currentMillis;
    }

    if (currentMillis - lastBlinkerCheckTime >= BLINKER_CHECK_INTERVAL) {
        Blinker.run();
        lastBlinkerCheckTime = currentMillis;

        temperature = dht.readTemperature();
        humidity = dht.readHumidity();
        
        uint16_t lux = lightMeter.readLightLevel();
        uint8_t lightPercentage = (lux * 100 / MAX_LUX > 100)? 100 : lux * 100 / MAX_LUX;
        
        // 读取土壤湿度并校准
        int soilMoistureRaw = analogRead(soilMoisturePin);
        soilMoisturePercentage = map(soilMoistureRaw, 0, 4095, 100, 0); // 假设 0 是最湿，4095 是最干
        soilMoisturePercentage = constrain(soilMoisturePercentage, 0, 100);

        kqwd.print(temperature);
        kqsd.print(humidity);
        trsd.print(soilMoisturePercentage);
        gz.print(lightPercentage);

        fszt.print(fanState);
        sbzt.print(pumpState);
        jrzt.print(heaterState);
    }

    if (currentMillis - lastButtonCheckTime >= BUTTON_CHECK_INTERVAL) {
        handleButtons();
        lastButtonCheckTime = currentMillis;
    }

    if (currentMillis - lastDisplayUpdateTime >= DISPLAY_UPDATE_INTERVAL) {
        updateDisplay();
        lastDisplayUpdateTime = currentMillis;
    }
}